{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# AppBuilder-Trace:更友好易用的可视化Debug方法\n",
    "\n",
    "在使用AppBuilder-SDK完成代码态开发可能会出现BUG，同时在运行Agent的过程中的黑盒问题，给Appbuilder的代码态使用带来了极大的不便。因此Appbuilder-SDK提供了DEBUG功能与Trace功能，帮助用户更友好、易用的调试代码。\n",
    "\n",
    "## DEBUG功能\n",
    "\n",
    "[DEBUG功能](https://github.com/baidubce/app-builder/blob/master/docs/quick_start/README.md#%E6%89%93%E5%8D%B0debug%E6%97%A5%E5%BF%97)\n",
    "\n",
    "- 开启DEBUG日志，可以打印出更多的日志信息，方便调试，包括且不限于：请求URL、请求头、请求参数等。\n",
    "\n",
    "### 打印DEBUG日志\n",
    "\n",
    "设置环境变量\n",
    "- 开启DEBUG:`export APPBUILDER_LOGLEVEL=DEBUG`\n",
    "- 关闭DEBUG:`export APPBUILDER_LOGLEVEL=INFO`\n",
    "\n",
    "- 也可以在代码中设置，优先级高于环境变量。\n",
    "\n",
    "```python\n",
    "# python\n",
    "appbuilder.logger.setLoglevel(\"DEBUG\")\n",
    "```\n",
    "```java\n",
    "//java\n",
    "System.setProperty(\"APPBUILDER_LOGLEVEL\", \"DEBUG\");\n",
    "```\n",
    "```go\n",
    "//golang\n",
    "os.Setenv(\"APPBUILDER_LOGLEVEL\", \"DEBUG\")\n",
    "```\n",
    "\n",
    "### 指定日志文件\n",
    "\n",
    "如果需要将日志输出到指定文件，方便落盘。默认输出为标准输出流。 可以设置环境变量APPBUILDER_LOGFILE,文件名及路径可以根据实际使用修改`export APPBUILDER_LOGFILE=/tmp/appbuilder.log`\n",
    "\n",
    "```python\n",
    "# python\n",
    "appbuilder.logger.setFilename(\"/tmp/appbuilder.log\")\n",
    "```\n",
    "```java\n",
    "//java\n",
    "System.setProperty(\"APPBUILDER_LOGLFILE\", \"/tmp/appbuilder.log\");\n",
    "```\n",
    "```golang\n",
    "// golang\n",
    "os.Setenv(\"APPBUILDER_LOGLEVEL\", \"/tmp/appbuilder.log\")\n",
    "```\n",
    "\n",
    "### DEBUG功能应用与正常运行状态\n",
    "\n",
    "- 我们将使用Appbuilder-SDK调用已创建好的Client应用进行测试\n",
    "\n",
    "示例中的应用为：说唱导师"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:29:34,682.682] _client.py [line:105] DEBUG [main-10719753420054307843] AppBuilder Secret key: Bearer your api key\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:appbuilder:AppBuilder Secret key: Bearer your api key\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:29:34,686.686] _client.py [line:207] DEBUG [main-10048254465741365719] Request header: {'X-Appbuilder-Sdk-Config': '{\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}', 'X-Appbuilder-Origin': 'appbuilder_sdk', 'X-Appbuilder-Request-Id': '68ab95ac-c503-4616-a094-50739292c3c1', 'X-Bce-Request-Id': '68ab95ac-c503-4616-a094-50739292c3c1', 'Authorization': 'Bearer your api key'}\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:appbuilder:Request header: {'X-Appbuilder-Sdk-Config': '{\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}', 'X-Appbuilder-Origin': 'appbuilder_sdk', 'X-Appbuilder-Request-Id': '68ab95ac-c503-4616-a094-50739292c3c1', 'X-Bce-Request-Id': '68ab95ac-c503-4616-a094-50739292c3c1', 'Authorization': 'Bearer your api key'}\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:29:34,687.687] _client.py [line:161] DEBUG [main-11077088795128889416] Service url: https://qianfan.baidubce.com/v2/app/conversation\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:appbuilder:Service url: https://qianfan.baidubce.com/v2/app/conversation\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:29:34,690.690] _session.py [line:57] DEBUG [main-9588862210139017928] Curl Command:\n",
      "curl -X POST -L 'https://qianfan.baidubce.com/v2/app/conversation' \\\n",
      "-H 'User-Agent: python-requests/2.32.3' \\\n",
      "-H 'Accept-Encoding: gzip, deflate' \\\n",
      "-H 'Accept: */*' \\\n",
      "-H 'Connection: keep-alive' \\\n",
      "-H 'X-Appbuilder-Sdk-Config: {\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}' \\\n",
      "-H 'X-Appbuilder-Origin: appbuilder_sdk' \\\n",
      "-H 'X-Appbuilder-Request-Id: 68ab95ac-c503-4616-a094-50739292c3c1' \\\n",
      "-H 'X-Bce-Request-Id: 68ab95ac-c503-4616-a094-50739292c3c1' \\\n",
      "-H 'Authorization: Bearer your api key' \\\n",
      "-H 'Content-Type: application/json' \\\n",
      "-d '{\"app_id\": \"4678492a-5864-472e-810a-654538d3503c\"}'\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:appbuilder:Curl Command:\n",
      "curl -X POST -L 'https://qianfan.baidubce.com/v2/app/conversation' \\\n",
      "-H 'User-Agent: python-requests/2.32.3' \\\n",
      "-H 'Accept-Encoding: gzip, deflate' \\\n",
      "-H 'Accept: */*' \\\n",
      "-H 'Connection: keep-alive' \\\n",
      "-H 'X-Appbuilder-Sdk-Config: {\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}' \\\n",
      "-H 'X-Appbuilder-Origin: appbuilder_sdk' \\\n",
      "-H 'X-Appbuilder-Request-Id: 68ab95ac-c503-4616-a094-50739292c3c1' \\\n",
      "-H 'X-Bce-Request-Id: 68ab95ac-c503-4616-a094-50739292c3c1' \\\n",
      "-H 'Authorization: Bearer your api key' \\\n",
      "-H 'Content-Type: application/json' \\\n",
      "-d '{\"app_id\": \"4678492a-5864-472e-810a-654538d3503c\"}'\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:29:35,116.116] _client.py [line:207] DEBUG [main-10660544649237524198] Request header: {'X-Appbuilder-Sdk-Config': '{\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}', 'X-Appbuilder-Origin': 'appbuilder_sdk', 'X-Appbuilder-Request-Id': '4e643ef9-e6f8-4b16-87db-81cda2cbb8de', 'X-Bce-Request-Id': '4e643ef9-e6f8-4b16-87db-81cda2cbb8de', 'Authorization': 'Bearer your api key'}\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:appbuilder:Request header: {'X-Appbuilder-Sdk-Config': '{\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}', 'X-Appbuilder-Origin': 'appbuilder_sdk', 'X-Appbuilder-Request-Id': '4e643ef9-e6f8-4b16-87db-81cda2cbb8de', 'X-Bce-Request-Id': '4e643ef9-e6f8-4b16-87db-81cda2cbb8de', 'Authorization': 'your api key'}\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:29:35,117.117] _client.py [line:161] DEBUG [main-11717755258005238516] Service url: https://qianfan.baidubce.com/v2/app/conversation/runs\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:appbuilder:Service url: https://qianfan.baidubce.com/v2/app/conversation/runs\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:29:35,119.119] _session.py [line:57] DEBUG [main-11593268707085638034] Curl Command:\n",
      "curl -X POST -L 'https://qianfan.baidubce.com/v2/app/conversation/runs' \\\n",
      "-H 'User-Agent: python-requests/2.32.3' \\\n",
      "-H 'Accept-Encoding: gzip, deflate' \\\n",
      "-H 'Accept: */*' \\\n",
      "-H 'Connection: keep-alive' \\\n",
      "-H 'X-Appbuilder-Sdk-Config: {\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}' \\\n",
      "-H 'X-Appbuilder-Origin: appbuilder_sdk' \\\n",
      "-H 'X-Appbuilder-Request-Id: 4e643ef9-e6f8-4b16-87db-81cda2cbb8de' \\\n",
      "-H 'X-Bce-Request-Id: 4e643ef9-e6f8-4b16-87db-81cda2cbb8de' \\\n",
      "-H 'Authorization: Bearer your api key' \\\n",
      "-H 'Content-Type: application/json' \\\n",
      "-d '{\"query\": \"以“上班狼狈却又追逐梦想“为主题进行一首说唱创作，保持押韵, 控制在50字以内\", \"stream\": false, \"conversation_id\": \"f7cd419c-d78c-4fbf-8ed4-c0b93c411381\", \"file_ids\": [], \"app_id\": \"4678492a-5864-472e-810a-654538d3503c\", \"tools\": null, \"tool_outputs\": null}'\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:appbuilder:Curl Command:\n",
      "curl -X POST -L 'https://qianfan.baidubce.com/v2/app/conversation/runs' \\\n",
      "-H 'User-Agent: python-requests/2.32.3' \\\n",
      "-H 'Accept-Encoding: gzip, deflate' \\\n",
      "-H 'Accept: */*' \\\n",
      "-H 'Connection: keep-alive' \\\n",
      "-H 'X-Appbuilder-Sdk-Config: {\"appbuilder_sdk_version\":\"0.9.3\",\"appbuilder_sdk_language\":\"python\",\"appbuilder_sdk_platform\":\"unknown\"}' \\\n",
      "-H 'X-Appbuilder-Origin: appbuilder_sdk' \\\n",
      "-H 'X-Appbuilder-Request-Id: 4e643ef9-e6f8-4b16-87db-81cda2cbb8de' \\\n",
      "-H 'X-Bce-Request-Id: 4e643ef9-e6f8-4b16-87db-81cda2cbb8de' \\\n",
      "-H 'Authorization: Bearer your api key' \\\n",
      "-H 'Content-Type: application/json' \\\n",
      "-d '{\"query\": \"以“上班狼狈却又追逐梦想“为主题进行一首说唱创作，保持押韵, 控制在50字以内\", \"stream\": false, \"conversation_id\": \"f7cd419c-d78c-4fbf-8ed4-c0b93c411381\", \"file_ids\": [], \"app_id\": \"4678492a-5864-472e-810a-654538d3503c\", \"tools\": null, \"tool_outputs\": null}'\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "上班路上忙追赶，狼狈模样也心甘。\n",
      "梦想照亮前方路，不畏艰辛往前看。\n",
      "脚步匆匆人憔悴，只为梦想能成真。\n",
      "努力奋斗不言弃，终有一天会翻身。\n",
      "\n",
      "这首简短的说唱以“上班狼狈却又追逐梦想”为主题，表达了追梦路上的艰辛与坚持，希望你喜欢。\n"
     ]
    }
   ],
   "source": [
    "import appbuilder\n",
    "import os\n",
    "\n",
    "appbuilder.logger.setLoglevel(\"DEBUG\")\n",
    "# 设置环境中的TOKEN，请替换为您的个人TOKEN\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = \"your api key\"\n",
    "\n",
    "# 从AppBuilder网页获取并传入应用ID，以下为说唱导师应用ID\n",
    "app_id = \"4678492a-5864-472e-810a-654538d3503c\"\n",
    "\n",
    "app_builder_client = appbuilder.AppBuilderClient(app_id)\n",
    "conversation_id = app_builder_client.create_conversation()\n",
    "\n",
    "answer = app_builder_client.run(conversation_id, \"以“上班狼狈却又追逐梦想“为主题进行一首说唱创作，保持押韵, 控制在50字以内\")\n",
    "print(answer.content.answer)\n",
    "\n",
    "appbuilder.logger.setLoglevel(\"INFO\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以看到DEBUG模式会截获并在控制台输出相应的运行节点信息,同时可以生成curl,辅助开发者实现请求复现\n",
    "\n",
    "## Trace功能\n",
    "\n",
    "[Trace功能](https://github.com/baidubce/app-builder/blob/master/docs/trace/README.md)\n",
    "\n",
    "### Trace环境的安装与启动\n",
    "\n",
    "Appbuilder-SDK的可视化跟踪前端基于Phoenix可视化软件如果未安装phoenix，需要先安装phoenix软件(这里提供清华源下载途径)\n",
    "\n",
    "#### Trace环境的安装\n",
    "\n",
    "```bash\n",
    "python3 -m pip install arize-phoenix==4.5.0 -i https://pypi.tuna.tsinghua.edu.cn/simple\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!python3 -m pip install arize-phoenix==4.5.0 -i https://pypi.tuna.tsinghua.edu.cn/simple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 启动phoenix服务\n",
    "\n",
    "控制台输入:`appbuilder_trace_server`,即可启动phoenix可视化软件,点击 http://localhost:8080/ 即可打开可视化界面\n",
    "\n",
    "- 要求 `appbuilder-sdk >= 0.9.1`\n",
    "\n",
    "### Trace框架功能展示\n",
    "\n",
    "Trace框架现阶段支持两种Trace信息展示方式\n",
    "\n",
    "- Phoenix可视化展示Trace到的Span信息\n",
    "  - `enable_phoenix = True`\n",
    "- 控制台输出Trace到的Span信息\n",
    "  - `enable_console = True`\n",
    "\n",
    "接下来流式运行Client应用，查看Phoenix效果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:30:10,683.683] tracer.py [line:293] INFO [main-11990101290407320544] OTLPSpanExporter endpoint: http://localhost:8080/v1/traces\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:appbuilder:OTLPSpanExporter endpoint: http://localhost:8080/v1/traces\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2024-08-21 20:30:10,684.684] tracer.py [line:351] INFO [main-10829791027654713596] AppBuilder Starting trace...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:appbuilder:AppBuilder Starting trace...\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "answer='' events=[Event(code=0, message='', status='done', event_type='function_call', content_type='function_call', detail={'text': {'arguments': {'origin_query': '以“上班狼狈却又追逐梦想“为主题进行一首说唱创作，保持押韵, 控制在50字以内'}, 'component_code': 'ChatAgent', 'component_name': '聊天助手'}}, usage=None, tool_calls=None)]\n",
      "answer='' events=[Event(code=0, message='', status='preparing', event_type='ChatAgent', content_type='status', detail={}, usage=None, tool_calls=None)]\n",
      "answer='Intro:' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': 'Intro:'}, usage=Usage(prompt_tokens=398, completion_tokens=0, total_tokens=398, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='\\n追逐' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '\\n追逐'}, usage=Usage(prompt_tokens=398, completion_tokens=0, total_tokens=398, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='梦想的路上' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '梦想的路上'}, usage=Usage(prompt_tokens=398, completion_tokens=0, total_tokens=398, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='，上班' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '，上班'}, usage=Usage(prompt_tokens=398, completion_tokens=0, total_tokens=398, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='狼狈不' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '狼狈不'}, usage=Usage(prompt_tokens=398, completion_tokens=0, total_tokens=398, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='慌张。' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '慌张。'}, usage=Usage(prompt_tokens=398, completion_tokens=0, total_tokens=398, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='\\n\\n' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '\\n\\n'}, usage=Usage(prompt_tokens=398, completion_tokens=16, total_tokens=414, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='Verse:' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': 'Verse:'}, usage=Usage(prompt_tokens=398, completion_tokens=16, total_tokens=414, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='\\n朝九晚' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '\\n朝九晚'}, usage=Usage(prompt_tokens=398, completion_tokens=16, total_tokens=414, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='五忙' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '五忙'}, usage=Usage(prompt_tokens=398, completion_tokens=16, total_tokens=414, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='又忙' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '又忙'}, usage=Usage(prompt_tokens=398, completion_tokens=16, total_tokens=414, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='，为了' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '，为了'}, usage=Usage(prompt_tokens=398, completion_tokens=16, total_tokens=414, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='生活奔波' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '生活奔波'}, usage=Usage(prompt_tokens=398, completion_tokens=16, total_tokens=414, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='忙。' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '忙。'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='\\n心中' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '\\n心中'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='却有梦想' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '却有梦想'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='在，' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '在，'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='不曾放弃' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '不曾放弃'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='追逐航' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '追逐航'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='。\\n' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '。\\n'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='\\nHook' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '\\nHook'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer=':\\n' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': ':\\n'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='梦想照亮' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '梦想照亮'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='前方路' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '前方路'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='，坚持' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '，坚持'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='信念不' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '信念不'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='认输。' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '认输。'}, usage=Usage(prompt_tokens=398, completion_tokens=30, total_tokens=428, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='\\n哪怕' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '\\n哪怕'}, usage=Usage(prompt_tokens=398, completion_tokens=58, total_tokens=456, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='上班再' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '上班再'}, usage=Usage(prompt_tokens=398, completion_tokens=58, total_tokens=456, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='狼狈，' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '狼狈，'}, usage=Usage(prompt_tokens=398, completion_tokens=58, total_tokens=456, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='也要勇敢' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '也要勇敢'}, usage=Usage(prompt_tokens=398, completion_tokens=58, total_tokens=456, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='追梦想' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '追梦想'}, usage=Usage(prompt_tokens=398, completion_tokens=58, total_tokens=456, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='。\\n' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '。\\n'}, usage=Usage(prompt_tokens=398, completion_tokens=58, total_tokens=456, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='\\n这首' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '\\n这首'}, usage=Usage(prompt_tokens=398, completion_tokens=73, total_tokens=471, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='简短的' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '简短的'}, usage=Usage(prompt_tokens=398, completion_tokens=73, total_tokens=471, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='rap以' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': 'rap以'}, usage=Usage(prompt_tokens=398, completion_tokens=73, total_tokens=471, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='“上班' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '“上班'}, usage=Usage(prompt_tokens=398, completion_tokens=79, total_tokens=477, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='狼狈却又' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '狼狈却又'}, usage=Usage(prompt_tokens=398, completion_tokens=79, total_tokens=477, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='追逐梦想”' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '追逐梦想”'}, usage=Usage(prompt_tokens=398, completion_tokens=79, total_tokens=477, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='为主题，' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '为主题，'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='通过押韵' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '通过押韵'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='的方式表达了' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '的方式表达了'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='即使生活' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '即使生活'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='艰辛，' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '艰辛，'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='也要坚持' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '也要坚持'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='追逐梦想的' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '追逐梦想的'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='决心。' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '决心。'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='希望你喜欢' events=[Event(code=0, message='', status='running', event_type='ChatAgent', content_type='text', detail={'text': '希望你喜欢'}, usage=Usage(prompt_tokens=398, completion_tokens=88, total_tokens=486, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='！' events=[Event(code=0, message='', status='done', event_type='ChatAgent', content_type='text', detail={'text': '！'}, usage=Usage(prompt_tokens=398, completion_tokens=105, total_tokens=503, name='ERNIE-4.0-8K-Preview'), tool_calls=None)]\n",
      "answer='' events=[Event(code=0, message='', status='success', event_type='ChatAgent', content_type='status', detail={}, usage=None, tool_calls=None)]\n",
      "answer='' events=[]\n",
      "[2024-08-21 20:30:19,396.396] tracer.py [line:355] INFO [main-11328972138384597399] AppBuilder Ending trace...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:appbuilder:AppBuilder Ending trace...\n"
     ]
    }
   ],
   "source": [
    "# 启动Appbuilder-SDK TRACE\n",
    "from appbuilder import AppBuilderTracer\n",
    "tracer=AppBuilderTracer(\n",
    "    enable_phoenix = True,\n",
    "    enable_console = False,\n",
    "    )\n",
    "\n",
    "\n",
    "import appbuilder\n",
    "import os\n",
    "\n",
    "# 启动跟踪器\n",
    "tracer.start_trace()\n",
    "\n",
    "# 设置环境中的TOKEN，替换为您的个人TOKEN\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = \"your api key\"\n",
    "\n",
    "# 从AppBuilder网页获取并传入应用ID，以下为说唱导师应用ID\n",
    "app_id = \"4678492a-5864-472e-810a-654538d3503c\"\n",
    "\n",
    "app_builder_client = appbuilder.AppBuilderClient(app_id)\n",
    "conversation_id = app_builder_client.create_conversation()\n",
    "\n",
    "answer = app_builder_client.run(conversation_id, \"以“上班狼狈却又追逐梦想“为主题进行一首说唱创作，保持押韵, 控制在50字以内\",stream = True)\n",
    "\n",
    "# 流式输出res\n",
    "for res in answer.content:\n",
    "    print(res)\n",
    "\n",
    "\n",
    "# 结束跟踪器\n",
    "tracer.end_trace()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 控制台输出跟踪到的Span节点信息\n",
    "- 可以在可视化界面查看跟踪信息如Client组件的调用链路，输入输出、消耗token数等信息\n",
    "- 点击某个调用链路，可以查看该调用链路详细信息，流式运行过程，HTTP-POST节点展示curl命令\n",
    "\n",
    "![Phoenix可视化界面展示](https://bj.bcebos.com/v1/appbuilder-sdk-components/cookbook-phoenix.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-08-21T07%3A36%3A31Z%2F-1%2Fhost%2Fd005f6e23bfc3f7439e0701baf497d1ff7afbd050343c650392569d83baa5ec6)\n",
    "\n",
    "\n",
    "### Phoneix可视化软件的进阶用法\n",
    "\n",
    "#### 1. 选择可视化展示的选项\n",
    "\n",
    "- 点击Columns，选择需要可视化展示的字段\n",
    "\n",
    "![选择可视化展示的选项](https://bj.bcebos.com/v1/appbuilder-sdk-components/%E4%BF%AE%E6%94%B9phoenix%E5%B1%95%E7%A4%BA%E5%8F%82%E6%95%B0.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-07-22T03%3A35%3A17Z%2F-1%2Fhost%2Ff9ff13fb2243ebbf1dd66008977a46def85aec56af5256be3f141fd36b6194c9)\n",
    "\n",
    "\n",
    "#### 2. 查看节点关键信息 \n",
    "\n",
    "- 点击需要查看的节点，查看节点关键信息，Info将展示input、ouput信息\n",
    "\n",
    "![查看节点关键信息 ](https://bj.bcebos.com/v1/appbuilder-sdk-components/Phoenix%E5%8F%AF%E8%A7%86%E5%8C%96%E7%95%8C%E9%9D%A2%EF%BC%883%EF%BC%89.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-07-22T03%3A36%3A11Z%2F-1%2Fhost%2Ffc471ccb9ecbc05eebf41f965e6df52132219f96bf688a46e6b6fa61f598088e)\n",
    "\n",
    "#### 3. 搜索目标节点 \n",
    "\n",
    "##### 依据节点类型搜索\n",
    "\n",
    "- 点击搜索框，输入节点类型，搜索目标节点(eg: span_kind == 'AGENT')\n",
    "- 在Traces界面，只能检索到根节点、在Spans界面，可以检索到所有节点\n",
    "\n",
    "![依据节点类型搜索](https://bj.bcebos.com/v1/appbuilder-sdk-components/span_kind_find.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-07-22T04%3A39%3A04Z%2F-1%2Fhost%2F5bb320731860407968af9693c43c5639611776d760769d29077bcb2e968b05d1)\n",
    "\n",
    "##### 依据节点信息检索\n",
    "\n",
    "- 依据节点信息检索可快速定位到目标节点\n",
    "\n",
    "![依据节点信息检索](https://bj.bcebos.com/v1/appbuilder-sdk-components/span_value_find.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-07-22T04%3A39%3A20Z%2F-1%2Fhost%2F43b20f9894586405e65195ebf6f86c21193812ab9ffd59f93287266e1a83ab03)\n",
    "\n",
    "##### 其他多种检索方式\n",
    "\n",
    "![其他多种检索方式](https://bj.bcebos.com/v1/appbuilder-sdk-components/every_span_find.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-07-22T04%3A39%3A35Z%2F-1%2Fhost%2Fa9b2dcf361416cf9a3727fc64d86bb370a5f24fc25286c53be15c5ecfd44e7e0)\n",
    "\n",
    "### Trace服务独立部署\n",
    "\n",
    "Phonenix可视化界面不但支持本地部署，还支持远程服务器部署\n",
    "\n",
    "#### 远程服务器启动Phoenix\n",
    "\n",
    "- 远程服务器部署Phoenix，需要提前安装好Docker环境\n",
    "运行`appbuilder_trace_server`命令，启动Phoenix服务\n",
    "\n",
    "- 本地运行Appbuilder Trace功能需要对`AppBuilderTracer`实例化时的参数进行修改,即可实现将Appbuilder-SDK的Trace信息发送到远程服务器\n",
    "\n",
    "```python\n",
    "from appbuilder import AppBuilderTracer\n",
    "tracer=AppBuilderTracer(\n",
    "    enable_phoenix = True,\n",
    "    enable_console = True,\n",
    "    host = \"远程服务器的IP地址\",\n",
    "    port = 8080,\n",
    "    )\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python-10",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
